#pragma once
#include "Util.hpp"
#include "data.hpp"
#include "httplib.h"
namespace aod
{
    const std::string dir = "./www";
    const std::string video_dir = "/video/";
    const std::string image_dir = "/image/";
    std::unique_ptr<TableVideo> p(new TableVideo()); // 共享资源 --- 可以设计为单例
    class Server
    {
    public:
        Server(int port) : _port(port) 
        {}
        ~Server() {}
        bool Run()
        {
            // 创建资源路径
            FileUtil(dir).CreateDirectory();
            FileUtil(dir + video_dir).CreateDirectory();
            FileUtil(dir + image_dir).CreateDirectory();
            // 搭建http服务器
            // 1、设置静态资源根目录
            _ser.set_mount_point("/", dir.c_str());
            // 2、添加请求-处理函数
            _ser.Post("/video", Insert);
            _ser.Delete("/video/(\\d+)", Delete);
            _ser.Put("/video/(\\d+)", Update);
            _ser.Get("/video/(\\d+)", SelectOne);
            _ser.Get("/video", SelectALL);
            _ser.listen("0.0.0.0", _port);
            std::cout << "服务器运行成功" << std::endl;
            return true;
        }

    private:
        static void ErrorRespond(httplib::Response &resp, const std::string reason)
        {
            resp.status = 500;
            resp.body = "{\"result\":\"false\", \"reason\":" + reason + "}";
            resp.set_header("Content_Type", "application/Json");
            return;
        }
        static void Insert(const httplib::Request &req, httplib::Response &resp)
        {
            if (!req.has_file("name") || !req.has_file("info") || !req.has_file("video") || !req.has_file("image"))
            {
                ErrorRespond(resp, "文件上传失败");
                return;
            }
            // MultipartFormData get_file_value(const char *key) const;
            httplib::MultipartFormData name = req.get_file_value("name");
            httplib::MultipartFormData info = req.get_file_value("info");
            httplib::MultipartFormData video = req.get_file_value("video");
            httplib::MultipartFormData image = req.get_file_value("image");

            std::string video_path = dir + video_dir + name.content + video.filename;
            if (FileUtil(video_path).SetContent(video.content) == false)
            {
                ErrorRespond(resp, "视频文件存储失败");
                return;
            }
            std::string image_path = dir + image_dir + name.content + image.filename;
            if (FileUtil(image_path).SetContent(image.content) == false)
            {
                ErrorRespond(resp, "图片文件存储失败");
                return;
            }
            Json::Value root;
            root["name"] = name.content; std::cout << name.content << std::endl;
            root["info"] = info.content; std::cout << info.content << std::endl;
            root["video"] = video_path; std::cout << video_path << std::endl;
            root["image"] = image_path; std::cout << image_path << std::endl;
            p->Insert(root);
        }
        static void Update(const httplib::Request &req, httplib::Response &resp)
        {
            // 获取ID
            int video_id = std::stoi(req.matches[1]);
            // 查看是否存在该视频信息
            Json::Value val;
            std::cout << req.body << std::endl;
            if (JsonUtil::UnSerialize(&val, req.body) == false)
            {
                ErrorRespond(resp, "上传数据格式有问题");
                return;
            }
            if (!p->Update(video_id, val))
            {
                ErrorRespond(resp, "跟新内容失败");
                return;
            }
        }
        static void Delete(const httplib::Request &req, httplib::Response &resp)
        {
            // 获取ID
            int video_id = std::stoi(req.matches[1]);
            std::cout << video_id << std::endl;
            // 查看是否存在该视频信息
            Json::Value out;
            if (p->SelectOne(video_id, &out) == false)
            {
                ErrorRespond(resp, "不存在该文件");
                return;
            }
            std::cout << "找到文件" << std::endl;
            std::string tmp;
            JsonUtil::Serialize(out, &tmp);
            std::cout << tmp << std::endl;
            // 删除视频和图片
            // std::string image_path = dir + image_dir + out["image"].asString();
            // std::string video_path = dir + image_dir + out["video"].asString();
            std::string image_path = out["image"].asString();
            std::cout << image_path << std::endl;
            std::string video_path = out["video"].asString();
            std::cout << video_path << std::endl;
            remove(image_path.c_str());
            remove(video_path.c_str());
            // 删除数据库中的内容
            if (!p->Delete(video_id))
            {
                ErrorRespond(resp, "数据库删除内容失败");
                return;
            }
            std::cout << "delete success" << std::endl;
        }
        static void SelectOne(const httplib::Request &req, httplib::Response &resp)
        {
            // 获取ID
            int video_id = std::stoi(req.matches[1]);
            // 查看是否存在该视频信息
            Json::Value out;
            if (p->SelectOne(video_id, &out) == false)
            {
                ErrorRespond(resp, "不存在该文件");
                return;
            }
            // 组织返回响应
            JsonUtil::Serialize(out, &resp.body);
            resp.set_header("Content_Type", "application/Json");
        }
        static void SelectALL(const httplib::Request &req, httplib::Response &resp)
        {
            bool flag = true; // 默认是全取
            std::string search;
            if (req.has_param("search"))
            {
                flag = false;
                search = req.get_param_value("search");
            }
            Json::Value out;
            if (flag)
            {
                if (p->SelectAll(&out) == false)
                {
                    ErrorRespond(resp, "不存在该文件");
                    return;
                }
            }
            else
            {
                if (p->SelectLike(search, &out) == false)
                {
                    ErrorRespond(resp, "不存在该文件");
                    return;
                }
            }
            JsonUtil::Serialize(out, &resp.body);
            resp.set_header("Content_Type", "application/Json");
        }

    private:
        int _port;
        httplib::Server _ser;
    };
}